namespace ScrumSprintMonitor.ConfigEditor
{
	#region #using Directives

	using System;
	using System.Collections.Generic;
	using System.Text;
	using System.Windows;

	using Implementation;

	using Infrastructure;

	using Microsoft.Practices.ServiceLocation;

	using Views.ConfigurationView;
	using Views.PresentationConfigurationEditorView;
	using Views.SprintConfigurationEditorView;

	#endregion

	public class XamlServiceLocator
	{
		private static readonly Dictionary<Type, object> serviceOverrideDictionary = new Dictionary<Type, object>();

		static XamlServiceLocator()
		{
			DesignerProperties.GetIsInDesignMode = (object x) => StubDesignerProperties.GetIsInDesignMode(null);

			if (DesignerProperties.GetIsInDesignMode(null))
			{
				NinjectContainerAbstraction.RegisterModule<NinjectAppDesignTimeModule>();

				NinjectContainerAbstraction.EnsureContainerIsSetUp();
			}
		}

		public IConfigurationViewModel ConfigurationViewModel
		{
			get { return Get<IConfigurationViewModel>(); }
		}

		public ISprintConfigurationEditorViewModel SprintConfigurationEditorViewModel
		{
			get { return Get<ISprintConfigurationEditorViewModel>(); }
		}

		public IPresentationConfigurationEditorViewModel PresentationConfigurationEditorViewModel
		{
			get { return Get<IPresentationConfigurationEditorViewModel>(); }
		}

		public static T Get<T>()
		{
			object obj;
			if (serviceOverrideDictionary.TryGetValue(typeof(T), out obj))
			{
				return (T) obj;
			}

			try
			{
				return ServiceLocator.Current.GetInstance<T>();
			}
			catch (Exception ex)
			{
				Get<ILogger<XamlServiceLocator>>().Error(ex, "Exception found while resolving service {0}", typeof(T));

				var message = new StringBuilder();
				do
				{
					message.AppendLine(ex.Message);

					ex = ex.InnerException;
					if (ex != null)
					{
						message.AppendLine();
						message.AppendLine("Inner Exception:");
					}
				} while (ex != null);

				MessageBox.Show(message.ToString());

				throw;
			}
		}

		public static void Assign<T>(T service) where T : class
		{
			if (service == default(T))
			{
				serviceOverrideDictionary.Remove(typeof(T));
			}
			else
			{
				serviceOverrideDictionary.Add(typeof(T), service);
			}
		}
	}
}